package org.ivwsqii.zookeeper.curator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CreateBuilder;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.listen.ListenerContainer;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.retry.RetryNTimes;
import org.apache.curator.retry.RetryUntilElapsed;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;

import java.nio.charset.Charset;
import java.util.List;

/************************************************
 * @ClassName: CuratorTest.java
 * @Tables:
 * @Author:     wyl
 * @CreateDate: 2019/4/30
 * @RevisionHistory:
 ***********************************************/
public class CuratorTest {
    private static final String CONNECTION_STRING = "192.168.1.204:2181";
    private static final Charset CHARSET=Charset.forName("UTF-8");
    public void connect() throws Exception {
        //baseSleepTimeMs：为初始sleep时间，maxRetries最大重试次数
        RetryPolicy exponential = new ExponentialBackoffRetry(3000, 5);
        //n：重试指定次数，sleepMsBetweenRetries：每次sleep固定的时间
//        RetryPolicy retryNTimes = new RetryNTimes(10, 1000);
//        //maxElapsedTimeMs:最大重试时间，sleepMsBetweenRetries是sleep的时间间隔
//        RetryPolicy retryUntilElapsed = new RetryUntilElapsed(10000, 1000);
//        CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(CONNECTION_STRING, exponential);
//        CuratorFramework curatorFramework1 = CuratorFrameworkFactory.newClient(CONNECTION_STRING, retryNTimes);
//        CuratorFramework curatorFramework2 = CuratorFrameworkFactory.newClient(CONNECTION_STRING, retryUntilElapsed);
        CuratorFramework client = CuratorFrameworkFactory.builder().
                connectString(CONNECTION_STRING)
                .sessionTimeoutMs(30000)
                .connectionTimeoutMs(15000)
                .retryPolicy(exponential)
                .namespace("TK")
                .build();
        client.start();
        Stat stat1 = client.checkExists().forPath("/curatorTest/test1/test");
        if (null != stat1){
            client.delete().guaranteed().deletingChildrenIfNeeded().withVersion(-1).forPath("/curatorTest/test1/test");
        }
        String dataString = client.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                .forPath("/curatorTest/test1/test","one".getBytes());
        String data1 = client.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.PERSISTENT)
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                .forPath("/curatorTest/test2/test","two".getBytes());
        System.out.println(dataString);
        client.delete()
                .guaranteed()
                .deletingChildrenIfNeeded()
                .withVersion(-1)
//                .inBackground(new BackgroundCallback() {
//                    @Override
//                    public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
//
//                    }
//                })
                .inBackground(((client1, event) -> {
                    System.out.println(event.getPath() + ", data=" + event.getData());
                    System.out.println("event type=" + event.getType());
                    System.out.println("event code=" + event.getResultCode());
                }))
                .forPath("/curatorTest/test2/test");
        Stat getDataStat = new Stat();
        byte[] bytes = client.getData()
                .storingStatIn(getDataStat)
                .forPath("/curatorTest/test1/test");
        System.out.println("getDataStat:" + getDataStat.toString() + "\n bytes:" + new String(bytes, CHARSET));
        Stat stat = client.setData()
                .withVersion(-1)
                .forPath("/curatorTest/test1/test","sadf".getBytes());
        System.out.println("stat:" + stat.toString());
        Stat getChildStat = new Stat();
        List<String> list = client.getChildren()
                .storingStatIn(getChildStat)
                .forPath("/curatorTest");
        System.out.println("stat:" + getChildStat.toString()+"\n list:"+list);

        NodeCache nodeCache = new NodeCache(client, "/curatorTest/test1/test");
        nodeCache.start(true);
        nodeCache.getListenable().addListener(()->{
            ChildData childData = nodeCache.getCurrentData();
            if (null != childData){
                System.out.println("path=" + childData.getPath() + ", data=" + childData.getData() + ";");
            }
        });


        PathChildrenCache childrenCache = new PathChildrenCache(client,"/curatorTest",true);
        childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
        System.out.println(childrenCache.getCurrentData().size());
        childrenCache.getListenable().addListener((client1, event)->{
            ChildData data = event.getData();
            switch (event.getType()){
                case INITIALIZED:
                    System.out.println("子节点cache初始化完成(StartMode为POST_INITIALIZED_EVENT的情况)");
                    System.out.println("INITIALIZED: " + childrenCache.getCurrentData().size());
                    break;
                case CHILD_ADDED:
                    System.out.println("添加子节点，path=" + data.getPath() + ", data=" + new String(data.getData()));
                    break;
                case CHILD_UPDATED:
                    System.out.println("更新子节点，path=" + data.getPath() + ", data=" + new String(data.getData()));
                    break;
                case CHILD_REMOVED:
                    System.out.println("删除子节点，path=" + data.getPath());
                    break;
                default:
                    System.out.println(event.getType());
            }
        });
        Thread.sleep(20000000);
    }

    public static void main(String[] args) throws Exception {
        CuratorTest test = new CuratorTest();
        test.connect();

    }
}
